/* 
* Copyright (C) 2011-2018 ShenZhen iBOXSaaS Information Technology Co.,Ltd. 
* 
* All right reserved. 
* 
* This software is the confidential and proprietary 
* information of iBOXSaaS Company of China. 
* ("Confidential Information"). You shall not disclose 
* such Confidential Information and shall use it only 
* in accordance with the terms of the contract agreement 
* you entered into with iBOXSaaS inc. 
* 
*/

package org.iboxpay.open.common.token;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;

/**
 * 
 * BaseKeyUtil.java
 * @author xuxiao
 * @date 2018/06/15
 */
public class BaseKeyUtil {
	
	/**
	 * 从文件中加载私钥
	 * @param file
	 * @return
	 * @throws InvalidKeySpecException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static PrivateKey getPrivateKey(String privateKeyStr) throws InvalidKeySpecException,
			NoSuchAlgorithmException {
		java.security.Security
				.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		String privateKeyPEM = privateKeyStr.replace("-----BEGIN RSA PRIVATE KEY-----", "")
						.replace("-----END RSA PRIVATE KEY-----", "").replaceAll("\\s", "");
		byte[] privateKeyDER = Base64.getDecoder().decode(privateKeyPEM);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));
	}
	
	/**
	 * 从文件中加载公钥
	 * @param file
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 */
	public static PublicKey getPublicKey(String publicKeyStr) throws NoSuchAlgorithmException,
			InvalidKeySpecException {
		String publicKeyPEM = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "")
						.replace("-----END PUBLIC KEY-----", "").replaceAll("\\s", "");

		byte[] publicKeyDER = Base64.getDecoder().decode(publicKeyPEM);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		return keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));
	}

	public static KeyPair createAndStoreKeyPair(File publicKeyFile, File privateKeyFile)
			throws Exception {
		KeyPair kp = createKeyPair();
		storeKeyToPem(kp.getPublic(), publicKeyFile);
		storeKeyToPem(kp.getPrivate(), privateKeyFile);
		return kp;
	}
	
	/**
	 * 创建秘钥对
	 * @return
	 * @throws NoSuchProviderException 
	 * @throws NoSuchAlgorithmException 
	 * @throws Exception
	 */
	public static KeyPair createKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
		// 生成公私钥
		int keySize = 512;
		SecureRandom sr = new SecureRandom();
		sr.nextBytes(new byte[64]);
		return generateRsaKey(keySize, sr);
	}
	
	/**
	 * 生成随机秘钥对
	 * @param keySizeInBits
	 * @param random
	 * @return
	 * @throws NoSuchProviderException 
	 * @throws NoSuchAlgorithmException 
	 */
	private static KeyPair generateRsaKey(int keySizeInBits, SecureRandom random)
			throws NoSuchAlgorithmException, NoSuchProviderException {
		Security.addProvider(new BouncyCastleProvider());
		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
		generator.initialize(keySizeInBits, random);
		return generator.generateKeyPair();
	}
	
	/**
	 * 将公、私钥保存到文件
	 * @param key    公、私钥
	 * @param file   保存路径
	 * @throws IOException
	 */
	public static void storeKeyToPem(Key key, File file) throws IOException {
		// pem文件保存目录不存在则创建目录
		if (!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		FileOutputStream os = new FileOutputStream(file);
		JcaPEMWriter pemWriter = new JcaPEMWriter(new OutputStreamWriter(os));
		pemWriter.writeObject(key);
		pemWriter.close();
	}
}
